package com.ruoyi.framework.shiro.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import com.ruoyi.project.cwsk.packge.domain.Package;
import com.ruoyi.project.cwsk.packge.service.IPackageService;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.ShiroConstants;
import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.common.exception.user.CaptchaException;
import com.ruoyi.common.exception.user.UserBlockedException;
import com.ruoyi.common.exception.user.UserDeleteException;
import com.ruoyi.common.exception.user.UserNotExistsException;
import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.RedisUtil;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.security.ShiroUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.service.PermissionService;
import com.ruoyi.project.cwsk.channel.domain.Channel;
import com.ruoyi.project.cwsk.channel.service.IChannelService;
import com.ruoyi.project.cwsk.channelsub.domain.ChannelSubUser;
import com.ruoyi.project.cwsk.channelsub.service.IChannelSubUserService;
import com.ruoyi.project.cwsk.cpgame.service.ICpGameService;
import com.ruoyi.project.system.user.domain.User;
import com.ruoyi.project.system.user.domain.UserStatus;
import com.ruoyi.project.system.user.service.IUserService;

/**
 * 登录校验方法
 * 
 * @author ruoyi
 */
@Component
public class LoginService
{
    @Autowired
    private PasswordService passwordService;

    @Autowired
    private IUserService userService;
    
    @Autowired
    private IChannelService channelService;
    
    @Autowired
    private RedisUtil redisUtil;
    
    @Autowired
    private PermissionService permission;
    
    @Autowired
    private IChannelSubUserService channelSubUserService;
    
    @Autowired
    private IPackageService packageService;
    
    @Autowired
    private ICpGameService cpGameService;

	@Autowired
	private CacheManager cacheManager;

    public static final String CURRENT_GAME_IDS="current_gameIds";
	public static final String CURRENT_USER_ID="userId";
	public static final String CURRENT_SUB_CIDS="current_sub_cids";//当前角色组员id列表
	public static final String CURRENT_SUB_UIDS="current_sub_uids";//当前角色组员id列表
	
	public static final String PROMOTER_CIDS="promoter_cid";//推广员自身推广的渠道
	public static final String YY_GAMES="yy_games";//运营组员自身推广的游戏
	
	public static final String PJ_CIDS="pj_cid"; //泡椒网下的渠道

	//CPA类型的渠道
	public static final String CHANNEL_CPA_CIDS="channel_cpa_cids";
	
	//CPS类型的渠道
	public static final String CHANNEL_CPS_CIDS="channel_cps_cids";
	public static final String CHANNEL_RECHARGE_RECORD_VIEWABLE_CPS_CIDS="channel_recharge_record_viewable_cps_cids";
	
	//公会类型的渠道
	public static final String CHANNEL_GUILD_CIDS="channel_guild_cids";
	
	//银狐运营推广渠道id
	public static final String PROMOTER_CHANNEL_IDS="promoter_channel_ids";
	//银狐运营角色所有用户
	public static final String YHYY_USER_IDS="yhyy_user_ids";
	//魔情业务角色所有用户
	public static final String MQYW_USER_IDS="mqyw_user_ids";
	//登录用户所有的cid（cps，cpa，guild）
	public static final String ALL_CIDS = "all_cids";
	//魔情运营的游戏列表
	public static final String MQYW_GAME_IDS = "mqyw_game_ids";
    

    /**
     * 登录
     */
    public User login(String username, String password)
    {
        // 验证码校验
        if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
                || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }

        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }

        // 查询用户信息
        User user = userService.selectUserByLoginName(username);

        if (user == null && maybeMobilePhoneNumber(username))
        {
            user = userService.selectUserByPhoneNumber(username);
        }

        if (user == null && maybeEmail(username))
        {
            user = userService.selectUserByEmail(username);
        }

        if (user == null)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
            throw new UserNotExistsException();
        }
        
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
            throw new UserDeleteException();
        }
        
        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
            throw new UserBlockedException();
        }

        passwordService.validate(user, password);

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        recordLoginInfo(user);

//        userInfo(user);
        return user;
    }

    private boolean maybeEmail(String username)
    {
        if (!username.matches(UserConstants.EMAIL_PATTERN))
        {
            return false;
        }
        return true;
    }

    private boolean maybeMobilePhoneNumber(String username)
    {
        if (!username.matches(UserConstants.MOBILE_PHONE_NUMBER_PATTERN))
        {
            return false;
        }
        return true;
    }

    /**
     * 记录登录信息
     */
    public void recordLoginInfo(User user)
    {
        user.setLoginIp(ShiroUtils.getIp());
        user.setLoginDate(DateUtils.getNowDate());
        userService.updateUserInfo(user);
    }
    
    /**
      * 用户数据放缓存
     * @param user
     */
    public void userInfo(User user) {
    	if(user==null){ return ; }
		Session session=ShiroUtils.getSession();
		Long userId=user.getUserId();

		Channel channel = null; 
		Channel subChannel = null;
		if(!permission.isAnyRoles("ROLE_CHANNEL_SUBUSER")){ //如果不是子用户（因为子用户数据在另一张表  所以要做特殊处理）
			//根据用户信息查询渠道商信息
			channel = channelService.findChannelByUser(userId);
			if(channel != null){ //是否允许渠道查看菜单信息
				session.setAttribute("gameIncomeStatPower", channel.getGameIncomestatPower());  	//保留游戏收益统计设置权限
				session.setAttribute("channelProfitPower", channel.getChannelProfitpower());
				session.setAttribute("registrationPower", channel.getRegistrationPower());
				session.setAttribute("rechargePower", channel.getRechargePower());
				session.setAttribute("allowGeneration", channel.getAllowGeneration());
				session.setAttribute("cpsRegistrationPower", channel.getCpsRegistrationPower());
				session.setAttribute("searchAscripUserPower", channel.getSearchAscripUserPower());
				session.setAttribute("iosRechargePower", channel.getIosRechargePower());
			}else{
				session.setAttribute("gameIncomeStatPower", 0);  	//保留游戏收益统计设置权限
				session.setAttribute("channelProfitPower", 0);
				session.setAttribute("registrationPower", 0);
				session.setAttribute("rechargePower", 0);
				session.setAttribute("allowGeneration", 0);
				session.setAttribute("cpsRegistrationPower", 0);
				session.setAttribute("searchAscripUserPower", 0);
				session.setAttribute("iosRechargePower", 0);
			}
		}else{ //如果是子用户
			ChannelSubUser subChannelInfo = channelSubUserService.findSubChannelByUser(userId);
			subChannel = channelService.findBySubUser(userId);  //根据子用户账号拿到父渠道信息,因为怕后边把父渠道权限叠到子渠道权限上边，所以重新声明了一个对象
			if(subChannel != null){ //保留是否允许用户查看CPS、CPA、充值明细信息
				session.setAttribute("gameIncomeStatPower", subChannelInfo.getGameIncomeStatPower()); //保留菜单查看权限
				session.setAttribute("channelProfitPower", subChannelInfo.getChannelProfitPower());
				session.setAttribute("registrationPower", subChannelInfo.getRegistrationPower());
				session.setAttribute("rechargePower", subChannelInfo.getRechargePower());
				session.setAttribute("allowGeneration", subChannelInfo.getAllowGeneration());
				session.setAttribute("cpsRegistrationPower", subChannelInfo.getCpsRegistrationPower());
			}else{
				session.setAttribute("gameIncomeStatPower", 0); //保留菜单查看权限
				session.setAttribute("channelProfitPower", 0);
				session.setAttribute("registrationPower", 0);
				session.setAttribute("rechargePower", 0);
				session.setAttribute("allowGeneration", 0);
				session.setAttribute("cpsRegistrationPower", 0);
			}
		}
		
		//如果当前用户是渠道商，就把该渠道商的渠道号全部找出来，以备查询
		//2015-12-29：渠道商新增添加子用户功能
		//2017-09-13：新增内部公会组长权限设置
		if(permission.isAnyRoles("ROLE_CHANNEL,ROLE_CHANNEL_SUBUSER,ROLE_NBGHZZ")){
			List<Package> pkgs = null;
			List<Package> h5pkgs = null;
			if(permission.isAnyRoles("ROLE_CHANNEL")){
				pkgs = packageService.findPackageByUserId(userId);

			}else if(permission.isAnyRoles("ROLE_CHANNEL_SUBUSER")){
				List<String> subCidList = channelSubUserService.findSubUserCid(userId); //针对看不懂的设计对子渠道做特殊处理
				if(CollectionUtils.isEmpty(subCidList)){
					subCidList.add("-1");
				}
				pkgs = packageService.findPackageByCids(subCidList); //根据子用户id查询他的所有包体
			}else{
				//内部公会组长下的子用户
				List<ChannelSubUser> subUserList = channelSubUserService.findByCreator(userId);
				//根据子用户id查询其下面所有的cid
				if(subUserList != null && subUserList.size() > 0){
					List<String> cidList= new ArrayList<String>();
					for(ChannelSubUser ext : subUserList){
						List<String> tempList = channelSubUserService.findSubUserCid(ext.getUserId());
						cidList.addAll(tempList);
					}
					if(cidList.size() <= 0)
						cidList.add("-1");
					pkgs = packageService.findPackageByCids(cidList);
				}
			}
			List<String> cpa=new ArrayList<String>();
			List<String> cps=new ArrayList<String>();
			List<String> guild=new ArrayList<String>();
			List<String> allCids=new ArrayList<String>();
			//保存可查看充值记录的渠道包id
			List<String> rechargeRecordViewableCpa = new ArrayList<String>();
			
			if(pkgs!=null && pkgs.size()>0){

				for(Package pkg:pkgs){
					//拿到所有类型的cic
					allCids.add(pkg.getCid());
					
					if(pkg.getModel().equals("GUILD")){
						guild.add(pkg.getCid());
						continue;
					}
					
					if(pkg.getModel().equals("CPA")){
						cpa.add(pkg.getCid());
						continue;
					}
					
					if(pkg.getModel().equals("CPS")){
					    String cid = pkg.getCid();
						cps.add(cid);
							rechargeRecordViewableCpa.add(cid);
						continue;
					}
				}
			}
			
			session.setAttribute(CHANNEL_CPA_CIDS, cpa);
			session.setAttribute(CHANNEL_CPS_CIDS, cps);
			session.setAttribute(CHANNEL_RECHARGE_RECORD_VIEWABLE_CPS_CIDS, rechargeRecordViewableCpa);
			session.setAttribute(CHANNEL_GUILD_CIDS, guild);
			session.setAttribute(ALL_CIDS, allCids);
			
			//确认渠道商是否有添加子用户的功能
			if (channel != null) {
				session.setAttribute("subUser", channel.getSubUser());
				session.setAttribute("model", channel.getModel());
			}
		}
		
		if(permission.isAnyRoles("ROLE_CHANNEL_GH")){
			List<Package> pkgs = packageService.findPackageByUserId(userId);
			List<String> cids_gh = new ArrayList<String>(pkgs.size());
			for (Package pkg : pkgs) {
				if ( "GUILD".equals(pkg.getModel()) && pkg.getEnabled()==1) {
					cids_gh.add(pkg.getCid());
					break ; //一个公会账号只允许有一个渠道包
				}
			}
			session.setAttribute(CHANNEL_GUILD_CIDS, cids_gh);
		}
		
		//商务和公会组员自己推广的渠道
		if(permission.isAnyRoles("ROLE_SW,ROLE_GH,ROLE_GHZZ")){
			Map<String,Object> params=new HashMap<String,Object>();
			params.put("promoterId", userId);
			List<Package> pkgs=packageService.findPackageByPromoterId(userId);
			List<String> cids=new ArrayList<String>();
			if(CollectionUtils.isNotEmpty(pkgs)){
				for(Package pkg:pkgs){
					cids.add(pkg.getCid());
				}
			}else{
				cids.add("XXNOCIDXX");
			}
			
			session.setAttribute(PROMOTER_CIDS, cids);
		}
		
		//商务组长角色，将组员的ID列表拿出来 修改：可以看到本组其他人的数据
		if(permission.isAnyRoles("ROLE_SWZZ")){
			List<String> cids = generateSubCids("'ROLE_SW','ROLE_SWZZ','ROLE_GH','ROLE_GHZZ'");
			session.setAttribute(CURRENT_SUB_CIDS, cids);
			session.setAttribute(CURRENT_SUB_UIDS, generateSubUids("'ROLE_SW','ROLE_SWZZ','ROLE_GH','ROLE_GHZZ'"));
		}

		if(permission.isAnyRoles("ROLE_SW")){
			List<String> cids = generateSubCids("'ROLE_SW','ROLE_SWZZ'");
			session.setAttribute(CURRENT_SUB_CIDS, cids);
			session.setAttribute(CURRENT_SUB_UIDS, generateSubUids("'ROLE_SW','ROLE_SWZZ'"));
		
			List<Integer> channelIdList = channelService.findChannelIdByPromoterId(userId);
			if(CollectionUtils.isEmpty(channelIdList)){
				channelIdList.add(-1);
			}
			
			session.setAttribute(PROMOTER_CHANNEL_IDS, channelIdList);				
		}
		
		//公会组长角色，将组员的ID列表拿出来 修改：可以看到本组其他人的数据
		if(permission.isAnyRoles("ROLE_GHZZ") || permission.isAnyRoles("ROLE_GH")){
			List<String> cids = generateSubCids("'ROLE_GH','ROLE_GHZZ'");
			session.setAttribute(CURRENT_SUB_CIDS, cids);
			session.setAttribute(CURRENT_SUB_UIDS, generateSubUids("'ROLE_GH','ROLE_GHZZ'"));
		}
		
		//运营组员角色，将运营的游戏找出来
		if(permission.isAnyRoles("ROLE_YY")){
			List<Integer> gameIds = cpGameService.findGameIdByOperationId(userId);
			if(CollectionUtils.isEmpty(gameIds)){
				gameIds=new ArrayList<Integer>(1);
				gameIds.add(-1);
			}
			session.setAttribute(YY_GAMES, gameIds);
		}

		if(permission.isAnyRoles("ROLE_SWZZ,ROLE_GHZZ")){
			List<Package> pkgs=packageService.findPackageByPromoterId(1L);  //admin 帐号的userId
			List<String> cids=new ArrayList<String>();
			if(CollectionUtils.isNotEmpty(pkgs)){
				for(Package pkg:pkgs){
					cids.add(pkg.getCid());
				}
			}
			session.setAttribute(PJ_CIDS, cids);
		}
		
    }
    
    
    /**
	 * 根据当前用户的角色，找出当前用户的下级用户所有的渠道号
	 * @param roles
	 * @return
	 */
	public List<String> generateSubCids(String roles) {
		List<String> subCids = packageService.findSubPackagesByRoles(roles);
		if(CollectionUtils.isEmpty(subCids)){
			subCids = new ArrayList<String>();
			subCids.add("XNOCIDX");
		}
		return subCids;
	}
	
	
	/**
	 * 根据当前用户的角色，查找下属角色的用户列表；
	 * @param roles
	 * @return
	 */
	public List<Long> generateSubUids(String roles) {

		List<Long> subUids = userService.findUserIdByRoleKeys(roles);
		
		if(CollectionUtils.isEmpty(subUids)){
			subUids = new ArrayList<Long>();
			subUids.add(-1L);
		}
		return subUids;
	}
    
}
